package algorithm;

import algorithm.sort.Sort;

import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author xutao
 * created 2020/3/16 13:22
 */
public class TestUtils {


    //生成随机数组
    public static Integer[] generatorRandomArray(int size, int rangeLeft, int rangeRight) {
        Integer[] arr = new Integer[size];
        Random random = new Random(System.currentTimeMillis());
        return random.ints(size, rangeLeft, rangeRight).boxed().collect(Collectors.toList()).toArray(arr);
    }


    //生成部分随机整体有序的数组
    public static Integer[] generatorOrderedRandomArray(int size, int randomSize, int rangeLeft, int rangeRight) {
        Integer[] arr = new Integer[size];
        Random random = new Random(System.currentTimeMillis());
        Integer[] array = random.ints(size, rangeLeft, rangeRight).boxed().sorted().collect(Collectors.toList()).toArray(arr);

        for (int i = 0; i < randomSize; i++) {
            int index = random.nextInt(size);
            array[index] = random.nextInt(rangeRight - rangeLeft) + rangeLeft;
        }
        return array;
    }


    public static <T extends Sort> void testSpeed(Class<T> clz, Integer[] arr) {
        String msgTemplate = "Sort Name: %s\t, Cost: %s\t, ArraySize:%s";
        try {
            Sort sort = clz.newInstance();
            long start = System.currentTimeMillis();
            sort.sort(arr);
            long end = System.currentTimeMillis();
            if (!isSorted(arr)) {
                throw new RuntimeException("排序错误！");
            }
            System.err.println(String.format(msgTemplate, sort.name(), (end - start) / 1000d, arr.length));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }


    public static void testAlgorithmSpeed(List<Class<? extends Sort>> list, Integer[] array) throws InterruptedException {
        if (list.isEmpty()){
            System.err.println("算法列表为空");
        }
        ThreadPoolExecutor service =(ThreadPoolExecutor) Executors.newFixedThreadPool(list.size());
        Thread.setDefaultUncaughtExceptionHandler((t,e)->{
            e.printStackTrace();
        });
        for (Class<? extends Sort> sortClass : list) {
            Integer[] arr = Arrays.copyOf(array, array.length);
            service.submit(()->{
                testSpeed(sortClass, arr);
            });
        }

        service.shutdown();
        while (!service.awaitTermination(10, TimeUnit.SECONDS)){
            System.out.println("sorting...");
        }
    }

    //验证数组是否排序成功
    public static boolean isSorted(Integer[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                return false;
            }
        }
        return true;
    }



    public  static <T> List<Class<? extends T>> getAlgorithms(Class<T> supperClass) throws ClassNotFoundException {
        String packageName = supperClass.getPackage().getName();
        String path = MainTest.class.getResource("/").getFile();
        String packagePath = packageName.replace(".", File.separator);
        File dir = new File(path,packagePath);
        List<Class<? extends T>> list = new LinkedList<>();
        for (File file : dir.listFiles()) {
            String fileName = file.getName().replace(".class", "");
            Class<?> aClass = Class.forName(packageName + "." + fileName);
            if (!aClass.isInterface()&&supperClass.isAssignableFrom(aClass)){
                Class<? extends T> subClass = aClass.asSubclass(supperClass);
                list.add(subClass);
            }
        }
        return list;
    }
}
